package com.fireXXX.job.analysis.dynproxy.util.http.valid;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.web.client.RestTemplate;

import java.net.Proxy;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;

/**
 * @description: TODO
 * @throws:
 * @author: zhuangzhang2
 * @date: 2020/04/28 11:12
 */
@Component
public class ValidRestTemplateHandler implements InitializingBean {

    @Qualifier("validRestTemplate")
    @Autowired
    private RestTemplate validRestTemplate;

    private HttpHeaders defaultHeaders = new HttpHeaders();

    private SimpleClientHttpRequestFactory httpRequestFactory = null;

    @EventListener(ApplicationReadyEvent.class)
    public void init() {
        httpRequestFactory = (SimpleClientHttpRequestFactory)validRestTemplate.getRequestFactory();
    }

    private String combineParam(Map<String, String> params) {
        String result = "";
        for (Map.Entry<String, String> entry : params.entrySet()) {
            if (result.length() == 0) {
                result += entry.getKey() + "=" + entry.getValue();
            } else {
                result += "&" + entry.getKey() + "=" + entry.getValue();
            }
        }

        return result;
    }

    public void setHttpProxy(Proxy proxy) {
        if (httpRequestFactory == null) {
            init();
        }

        httpRequestFactory.setProxy(proxy);
    }

    public void setEncode(Charset charset) {
        if (ObjectUtils.isEmpty(validRestTemplate.getMessageConverters())) {
            return;
        }

        List<HttpMessageConverter<?>> messageConverters = validRestTemplate.getMessageConverters();
        for (int i = 0; i < messageConverters.size(); i++) {
            HttpMessageConverter<?> httpMessageConverter = messageConverters.get(i);
            if (httpMessageConverter.getClass().equals(StringHttpMessageConverter.class)) {
                messageConverters.set(i, new StringHttpMessageConverter(charset));
            }
        }
    }

    private RestTemplate getRestTemplate(String url) {
        return validRestTemplate;
    }

    public <T, B> T doPost(String url, B body, Class<T> responseType) {
        RestTemplate invoker = getRestTemplate(url);

        return invoker.exchange(url,
                HttpMethod.POST,
                new HttpEntity(body, defaultHeaders),
                responseType)
                .getBody();
    }

    public <T, B> T doPost(String url, B body, HttpHeaders headers, Class<T> responseType) {
        RestTemplate invoker = getRestTemplate(url);

        return invoker.exchange(url,
                HttpMethod.POST,
                new HttpEntity(body, headers),
                responseType)
                .getBody();
    }

    public <T> int doGetStatusCode(String url, Class<T> responseType) {
        RestTemplate invoker = getRestTemplate(url);

        return invoker.getForEntity(url,
                responseType)
                .getStatusCodeValue();
    }

    public <T> T doGet(String url, Class<T> responseType) {
        RestTemplate invoker = getRestTemplate(url);

        return invoker.getForEntity(url,
                responseType)
                .getBody();
    }

    public <T> T doGet(String url, Class<T> responseType, Map<String, String> uriVariables) {
        RestTemplate invoker = getRestTemplate(url);

        if (!url.contains("?")) {
            url += "?" + combineParam(uriVariables);
        } else {
            url += "&" + combineParam(uriVariables);
        }

        return invoker.exchange(url,
                    HttpMethod.GET,
                    new HttpEntity(defaultHeaders),
                    responseType)
                .getBody();
    }

    public <T> T doGet(String url, HttpHeaders headers, Class<T> responseType, Map<String, String> uriVariables) {
        RestTemplate invoker = getRestTemplate(url);

        if (!url.contains("?")) {
            url += "?" + combineParam(uriVariables);
        } else {
            url += "&" + combineParam(uriVariables);
        }

        return invoker.exchange(url,
                    HttpMethod.GET,
                    new HttpEntity(headers),
                    responseType)
                .getBody();
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
        defaultHeaders.setContentType(type);
        defaultHeaders.add("Accept", MediaType.APPLICATION_JSON.toString());

        setEncode(StandardCharsets.UTF_8);
    }
}